﻿namespace Sidvall.Serialization
{
    public static class ObjectExtension
    {
        #region ToEnum

        public static T ToEnum<T>(this object value, T defaultValue) where T : struct
        {
            var result = value.ToNullableEnum<T>();
            if (result == null)
                return defaultValue;
            return result.Value;
        }

        #endregion
        #region ToBoolean

        public static bool ToBoolean(this object value, bool defaultValue)
        {
            var result = value.ToNullableBoolean();
            if (result == null)
                return defaultValue;
            return result.Value;
        }

        #endregion
        #region ToChar

        public static char ToChar(this object value, char defaultValue)
        {
            char? result;

            result = value.ToNullableChar();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToDateTime

        public static System.DateTime ToDateTime(this object value, System.DateTime defaultValue)
        {
            System.DateTime? result;

            result = value.ToNullableDateTime();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToDateTimeOffset

        public static System.DateTimeOffset ToDateTimeOffset(this object value, System.DateTimeOffset defaultValue)
        {
            System.DateTimeOffset? result;

            result = value.ToNullableDateTimeOffset();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToDecimal

        public static decimal ToDecimal(this object value, decimal defaultValue)
        {
            decimal? result;

            result = value.ToNullableDecimal();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToDouble

        public static double ToDouble(this object value, double defaultValue)
        {
            double? result;

            result = value.ToNullableDouble();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToByte

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int8")]
        public static byte ToByte(this object value, byte defaultValue)
        {
            byte? result;

            result = value.ToNullableByte();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToInt16

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int16")]
        public static short ToInt16(this object value, short defaultValue)
        {
            short? result;

            result = value.ToNullableInt16();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToInt32

        public static int ToInt32(this object value, int defaultValue)
        {
            int? result;

            result = value.ToNullableInt32();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToInt64

        public static long ToInt64(this object value, long defaultValue)
        {
            long? result;

            result = value.ToNullableInt64();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToSingle

        public static float ToSingle(this object value, float defaultValue)
        {
            float? result;

            result = value.ToNullableSingle();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion
        #region ToTimeSpan

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "Sidvall.Serialization.ObjectExtension.ToNullableTimeSpan(System.Object)")]
        public static System.TimeSpan ToTimeSpan(this object value, System.TimeSpan defaultValue)
        {
            var result = value.ToNullableTimeSpan();
            if (result == null)
                return defaultValue;
            return result.Value;
        }
        public static System.TimeSpan ToTimeSpan(this object value, System.TimeSpan defaultValue, System.IFormatProvider provider)
        {
            var result = value.ToNullableTimeSpan(provider);
            if (result == null)
                return defaultValue;
            return result.Value;
        }

        #endregion
        #region ToGuid

        public static System.Guid ToGuid(this object value, System.Guid defaultValue)
        {
            System.Guid? result;

            result = value.ToNullableGuid();
            if (result == null)
                return defaultValue;

            return result.Value;
        }

        #endregion

        #region ToNullableEnum

        public static T? ToNullableEnum<T>(this object value) where T : struct
        {
            if (value == null)
                return null;
            if (value is T)
                return (T)value;
            return value.ToString(null).ToNullableEnum<T>();
        }

        #endregion
        #region ToNullableBoolean

        public static bool? ToNullableBoolean(this object value)
        {
            if (value == null)
                return null;
            if (value is bool)
                return (bool)value;
            return value.ToString(null).ToNullableBoolean();
        }

        #endregion
        #region ToNullableChar

        public static char? ToNullableChar(this object value)
        {
            if (value == null)
                return null;
            if (value is char)
                return (char)value;
            return value.ToString(null).ToNullableChar();
        }

        #endregion
        #region ToNullableDateTime

        public static System.DateTime? ToNullableDateTime(this object value)
        {
            if (value == null)
                return null;
            if (value is System.DateTime)
                return (System.DateTime)value;
            return value.ToString(null).ToNullableDateTime();
        }
        public static System.DateTime? ToNullableDateTime(this object value, System.DateTimeKind kind)
        {
            if (value == null)
                return null;
            if (value is System.DateTime)
                return (System.DateTime)value;
            return value.ToString(null).ToNullableDateTime(kind);
        }
        public static System.DateTime? ToNullableDateTime(this object value, System.IFormatProvider provider, System.Globalization.DateTimeStyles styles)
        {
            if (value == null)
                return null;
            if (value is System.DateTime)
                return (System.DateTime)value;
            return value.ToString(null).ToNullableDateTime(provider, styles);
        }
        public static System.DateTime? ToNullableDateTime(this object value, System.IFormatProvider provider, System.Globalization.DateTimeStyles styles, System.DateTimeKind kind)
        {
            if (value == null)
                return null;
            if (value is System.DateTime)
                return (System.DateTime)value;
            return value.ToString(null).ToNullableDateTime(provider, styles, kind);
        }

        #endregion
        #region ToNullableDateTimeOffset

        public static System.DateTimeOffset? ToNullableDateTimeOffset(this object value)
        {
            if (value == null)
                return null;
            if (value is System.DateTimeOffset)
                return (System.DateTimeOffset)value;
            return value.ToString(null).ToNullableDateTimeOffset();
        }

        #endregion
        #region ToNullableDecimal

        public static decimal? ToNullableDecimal(this object value)
        {
            if (value == null)
                return null;
            if (value is decimal)
                return (System.Decimal)value;
            return value.ToString(null).ToNullableDecimal();
        }
        public static decimal? ToNullableDecimal(this object value, System.Globalization.NumberStyles style, System.IFormatProvider provider)
        {
            if (value == null)
                return null;
            if (value is decimal)
                return (System.Decimal)value;
            return value.ToString(null).ToNullableDecimal(style, provider);
        }

        #endregion
        #region ToNullableDouble

        public static double? ToNullableDouble(this object value)
        {
            if (value == null)
                return null;
            if (value is double)
                return (System.Double)value;
            return value.ToString(null).ToNullableDouble();
        }
        public static double? ToNullableDouble(this object value, System.Globalization.NumberStyles style, System.IFormatProvider provider)
        {
            if (value == null)
                return null;
            if (value is double)
                return (System.Double)value;
            return value.ToString(null).ToNullableDouble(style, provider);
        }

        #endregion
        #region ToNullableByte

        public static byte? ToNullableByte(this object value)
        {
            if (value == null)
                return null;
            if (value is byte)
                return (byte)value;
            return value.ToString(null).ToNullableByte();
        }

        #endregion
        #region ToNullableInt16

        public static short? ToNullableInt16(this object value)
        {
            if (value == null)
                return null;
            if (value is short)
                return (short)value;
            return value.ToString(null).ToNullableInt16();
        }

        #endregion
        #region ToNullableInt32

        public static int? ToNullableInt32(this object value)
        {
            if (value == null)
                return null;
            if ((value is int) || (value is long))
                return (int)value;
            return value.ToString(null).ToNullableInt32();
        }
        public static int? ToNullableInt32(this object value, System.Globalization.NumberStyles style, System.IFormatProvider provider)
        {
            if (value == null)
                return null;
            if ((value is int) || (value is long))
                return (int)value;
            return value.ToString(null).ToNullableInt32(style, provider);
        }

        #endregion
        #region ToNullableInt64

        public static long? ToNullableInt64(this object value)
        {
            if (value == null)
                return null;
            if (value is long)
                return (long)value;
            return value.ToString(null).ToNullableInt64();
        }
        public static long? ToNullableInt64(this object value, System.Globalization.NumberStyles style, System.IFormatProvider provider)
        {
            if (value == null)
                return null;
            if (value is long)
                return (long)value;
            return value.ToString(null).ToNullableInt64(style, provider);
        }

        #endregion
        #region ToNullableSingle

        public static float? ToNullableSingle(this object value)
        {
            if (value == null)
                return null;
            if (value is float)
                return (float)value;
            return value.ToString(null).ToNullableSingle();
        }

        #endregion
        #region ToNullableTimeSpan

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "Sidvall.Serialization.StringExtension.ToNullableTimeSpan(System.String)")]
        public static System.TimeSpan? ToNullableTimeSpan(this object value)
        {
            if (value == null)
                return null;
            if (value is System.TimeSpan)
                return (System.TimeSpan)value;
            return value.ToString(null).ToNullableTimeSpan();
        }
        public static System.TimeSpan? ToNullableTimeSpan(this object value, System.IFormatProvider provider)
        {
            if (value == null)
                return null;
            if (value is System.TimeSpan)
                return (System.TimeSpan)value;
            return value.ToString(null).ToNullableTimeSpan(provider);
        }

        #endregion
        #region ToNullableGuid

        public static System.Guid? ToNullableGuid(this object value)
        {
            if (value == null)
                return null;
            if (value is System.Guid)
                return (System.Guid)value;
            return value.ToString(null).ToNullableGuid();
        }

        #endregion
        #region ToString

        public static string ToString(this object value, string defaultValue)
        {
            if (value == null)
                return defaultValue;
            var stringValue = value as string;
            if (stringValue != null)
                return stringValue;
            return value.ToString();
        }

        #endregion
    }
}
